#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libsck.h>
#include <libthrd.h>
#include <libipc.h>
#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "workflow_struct.h"
#include "gestion_client.h"
#include "processParser.h"
#include <ctype.h>
#ifndef NULL
#define NULL   ((void *) 0)
#endif
char * fichierUsers = "users";		/* contient le fichier utilisateur */
struct tableUser* UserConnect;		/* tableau users connectes */
struct boite listBoite;				/* table boite admin listen */
struct tableProcess * tableProcess;	/* table process */
//renvoie le nombre de chiffre d'un nombre x
int nbChiffres(int nombre) {
	return floor(log(nombre)) + 1;
}

char * ls_process(int process) {	/* envoi etat process <id> */
	char * message = NULL;
	int size_message = 0;
	P(VERROUTABLEPROCESS);
	if (tableProcess->nbProcesses < process) {	/* control existance */
		message = calloc(strlen("Processus inexistant\n") + 1, sizeof(char));
		sprintf(message, "Processus inexistant\n");
	} else {
		int i;
		struct process * processCourant = tableProcess->processes[process - 1];
		for (i = 0; i < processCourant->nbActivities; i++) {
			char * temp = calloc(strlen("Activite numero ") + nbChiffres(i + 1)
					+ strlen(":") + 1, sizeof(char));
			sprintf(temp, "Activite numero %d:", i + 1);
			message = realloc(message, size_message + strlen(temp));
			memcpy(message + size_message, temp, strlen(temp));
			size_message += strlen(temp);
			free(temp);

			char * stringActivite = activiteToString(
					processCourant->activities[i]);
			message = realloc(message, size_message + strlen(stringActivite));
			memcpy(message + size_message, stringActivite, strlen(
					stringActivite));
			size_message += strlen(stringActivite);
			printf("message: %s\n",stringActivite);
			free(stringActivite);
		}
		for (i = 0; i < processCourant->nbTransitions; i++) {
			char * temp = calloc(strlen("Transition numero ") + nbChiffres(i
					+ 1) + strlen(":") + 1, sizeof(char));
			sprintf(temp, "Transition numero %d:", i + 1);
			message = realloc(message, size_message + strlen(temp));
			memcpy(message + size_message, temp, strlen(temp));
			size_message += strlen(temp);
			free(temp);

			char * stringTransition = transitionToString(
					processCourant->transitions[i]);
			message = realloc(message, size_message + strlen(stringTransition));
			memcpy(message + size_message, stringTransition, strlen(
					stringTransition));
			size_message += strlen(stringTransition);
			printf("message: %s\n",stringTransition);
			free(stringTransition);

		}
		for (i = 0; i < processCourant->nbVariables; i++) {
			char * temp = calloc(strlen("Variable numero ") + nbChiffres(i + 1)
					+ strlen(":") + 1, sizeof(char));
			sprintf(temp, "Variable numero %d:", i + 1);
			message = realloc(message, size_message + strlen(temp));
			memcpy(message + size_message, temp, strlen(temp));
			size_message += strlen(temp);
			free(temp);

			char * stringVariable = variableToString(
					processCourant->variables[i]);
			message = realloc(message, size_message + strlen(stringVariable));
			memcpy(message + size_message, stringVariable, strlen(
					stringVariable));
			size_message += strlen(stringVariable);
			printf("message: %s\n",stringVariable);
			free(stringVariable);
		}
		message = realloc(message, size_message + 1);
		message[size_message] = '\0';
	}
	V(VERROUTABLEPROCESS);
	return message;
}

//permet de donner la l'utilisateur les activites qu'il peut valider pour tout les processus(commande ls)
char * activites_accessibles(int process, char * idActivity, char *login) {
	char * message = NULL;
	int size_message = 0;
	P(VERROUTABLEPROCESS);
	if (tableProcess->nbProcesses < process) {
		message = calloc(strlen("Processus inexistant\n") + 1, sizeof(char));
		sprintf(message, "Processus inexistant\n");
	} else {
		if (idActivity == NULL) {
			//Liste toutes les activites que l'utilisateur peut valider
			int i;
			for (i=0;i<tableProcess->nbProcesses;i++){
				if (tableProcess->processes[i]->state!=COMPLETED){
					int nbActivites;
					struct activity ** activity=findByPerformer(login,tableProcess->processes[i],&nbActivites);
					if (activity!=NULL){
						char * temp=malloc(strlen("Process numero :\n")+nbChiffres(i+1)+1);
						sprintf(temp,"Process numero %d:\n",i+1);
						message=realloc(message,size_message+strlen(temp));
						memcpy(message+size_message,temp,strlen(temp));
						size_message+=strlen(temp);
						free(temp);
						int i;
						for (i=0;i<nbActivites;i++){
							char * retour=activiteToShortString(*activity[i],1);
							message=realloc(message,size_message+strlen(retour));
							memcpy(message+size_message,retour,strlen(retour));
							size_message+=strlen(retour);
							free(retour);
						}
					}
				}
			}
			message = realloc(message, size_message + 1);
			message[size_message] = '\0';
		} else {
			//on veut qu'une activite mais faut vérifier qu'elle est bonne et possible a valider
			int activity = activityById(idActivity,
					tableProcess->processes[process - 1]);
			if (tableProcess->processes[process - 1]->nbActivities < activity) {
				message = calloc(strlen("Activite inexistante\n") + 1,
						sizeof(char));
				sprintf(message, "Activite inexistante\n");
			} else {
				//l'activite existe dans le process mais faut tester si on peut la valider
#ifdef VERBOSE
				fprintf(stderr, "Process:%d,login:%s\n", process, login);
#endif
				int nbActivites;
				struct activity ** activity=findByPerformer(login,tableProcess->processes[process-1],&nbActivites);
				if (activity==NULL){
					message=calloc(strlen("Pas d'activite de validable pour l'utilisateur dans ce process\n")+1,sizeof(char));
					sprintf(message,"Pas d'activite de validable pour l'utilisateur dans ce process\n");
				}
				else{
					//L'utilisateur peut valider l'activite mais est-ce la meme?
					int i;
					for (i=0;i<nbActivites;i++){
						if (strcmp(activity[i]->id,idActivity)==0){
							message=activiteToShortString(*activity[i],0);
						}
					}
					if (message==NULL){
						message=calloc(strlen("L'activite specifiee n'est pas validable par l'utilisateur\n")+1,sizeof(char));
						sprintf(message,"L'activite specifiee n'est pas validable par l'utilisateur\n");
					}
				}
			}

		}

	}
	V(VERROUTABLEPROCESS);
	return message;
}
int typeValide(char * value, char * type) {
	if (strcmp(type, "int") == 0) {
		int i;
		while (i < strlen(value) && isdigit(value[i])) {
			i++;
		}
		if (i == strlen(value)) {
			return 0;
		}
	}
	if (strcmp(type, "bool") == 0) {
		if (strcmp(value, "true") != 0 && strcmp(value, "false") != 0) {
			return 0;
		}
	}
	return 1;
}

//gere les validation de conditions
int conditionValide(char * condition, struct variable * variables,
		int nbVariables) {
	int idxvar = 0;
	while (isalpha(condition[idxvar])) {
		idxvar++;
	}
	char * var = calloc(idxvar + 1, sizeof(char));
	memcpy(var, condition, idxvar);
	int idxOp = idxvar;
	while (!isalpha(condition[idxOp])) {
		idxOp++;
	}
	char * op = calloc(idxOp + 1 - idxvar, sizeof(char));
	memcpy(op, condition + idxvar, idxOp - idxvar);
	char * value = calloc(strlen(condition) - idxOp + 1, sizeof(char));
	memcpy(value, condition + idxOp, strlen(condition) - idxOp);
#ifdef VERBOSE
	fprintf(stderr, "var:%s,op:%s,value:%s\n", var, op, value);
#endif
	struct variable * variable = valeur(variables, var, nbVariables);
	if (strcmp(variable->type, "int") == 0) {
		int val1 = atoi(variable->value);
		int val2 = atoi(value);
		if (strcmp(op, "==") == 0) {
			return val1 == val2;
		}
		if (strcmp(op, "!=") == 0) {
			return val1 != val2;
		}
		if (strcmp(op, "<") == 0) {
			return val1 < val2;
		}
		if (strcmp(op, ">") == 0) {
			return val1 > val2;
		}
		if (strcmp(op, ">=") == 0) {
			return val1 >= val2;
		}
		if (strcmp(op, "<=") == 0) {
			return val1 == val2;
		}
	}
	if (strcmp(variable->type, "string") == 0) {
		char * val1 = variable->value;
		char * val2 = value;
		if (strcmp(op, "==") == 0) {
			return strcmp(val1, val2) == 0;
		}
		if (strcmp(op, "!=") == 0) {
			return strcmp(val1, val2) != 0;
		}
	}
	if (strcmp(variable->type, "bool") == 0) {
		int val1;
		int val2;
		if (strcmp(variable->value, "true")) {
			val1 = 1;
		} else {
			val1 = 0;
		}
		if (strcmp(value, "true")) {
			val2 = 1;
		} else {
			val2 = 0;
		}
		if (strcmp(op, "==") == 0) {
			return val1 == val2;
		}
		if (strcmp(op, "!=") == 0) {
			return val1 != val2;
		}
	}
	return 0;
}
void gestionTransition(struct process * process,struct transition ** transitions,struct activity activite,int nbTransitions){
	if (nbTransitions==1){
		int idActivite=activityById(transitions[0]->to,process);
		if (allCompleted(process,transitions[0]->to)){
			process->activities[idActivite].state=RUNNING;
		}
	}
	else{
		int i=0;
		for (i=0;i<nbTransitions;i++){
			if (transitions[i]->condition==NULL){
				int idActivite=activityById(transitions[i]->to,process);
				if (allCompleted(process,transitions[0]->to)){
					process->activities[idActivite].state=RUNNING;
				}
			}
			else{
				if (conditionValide(transitions[i]->condition,process->variables,process->nbVariables)){
					int idActivite=activityById(transitions[i]->to,process);
					if (allCompleted(process,transitions[0]->to)){
						process->activities[idActivite].state=RUNNING;
					}
				}
			}
		}
	}
}


char * validerActivite(struct process* process, int activite, int socket) {
	char * message;
	char ** input = process->activities[activite].input;
	int nbInput = process->activities[activite].nbInput;
	int i;
	if (nbInput > 0) {
		envoie_message(socket, "Variables Input:\n");
	}
	for (i = 0; i < nbInput; i++) {
		char * chaine = NULL;
		envoie_message(socket, input[i]);
		envoie_message(socket, ":");
		struct variable* var = valeur(process->variables, input[i],
				process->nbVariables);
		envoie_message(socket, var->value);
		envoie_message(socket, "\n");
		free(chaine);
	}
	char ** output = process->activities[activite].output;
	int nbOutput = process->activities[activite].nbOutput;
	for (i = 0; i < nbOutput; i++) {
		//Pour chaque variable output on va demander a l'utilisateur de la saisir
		envoie_message(socket, "Valeur pour la variable ");
		envoie_message(socket, output[i]);
		envoie_message(socket, ":");
		struct variable* var = valeur(process->variables, output[i],
				process->nbVariables);
		char * value = lit_commande(socket);
		if (typeValide(value, var->type) == 1) {
			if (var->value != NULL) {
				free(var->value);
			}
			var->value = value;
		} else {
			message
					= calloc(
							strlen(
									"Valeur de la Variable ne concorde pas avec le type\n")
									+ 1, sizeof(char));
			sprintf(message,
					"Valeur de la Variable ne concorde pas avec le type\n");
			return message;
		}
	}
	process->activities[activite].state = COMPLETED;
	if (process->nbActivities == activite + 1) {
		process->state = COMPLETED;
	} else {
		int nbTransitions;
		struct transition ** transitions = findTransitions(process,
				process->activities[activite], &nbTransitions);
		if (transitions == NULL) {
			process->state = COMPLETED;
		} else {
			gestionTransition(process, transitions,
					process->activities[activite], nbTransitions);
		}
		free(transitions);

	}


	message = calloc(strlen("Activitee Validee\n") + 1, sizeof(char));
	sprintf(message, "Activitee Validee\n");
	return message;
}

//Valide une activite
char * valider(int process, char * idActivity, char *login, int socket) {
	char * message = NULL;
	P(VERROUTABLEPROCESS);
	//On verifie que le numero de Process existe
	if (tableProcess->nbProcesses<process){
		message=calloc(strlen("Processus inexistant\n")+1,sizeof(char));
		sprintf(message,"Processus inexistant\n");
	}
	else{
		int activity=activityById(idActivity,tableProcess->processes[process-1]);
		//Verification de l'existance de l'activite
		if (tableProcess->processes[process-1]->nbActivities<activity){
			message=calloc(strlen("Activite inexistante\n")+1,sizeof(char));
			sprintf(message,"Activite inexistante\n");
		}
		else{
			int nbActivites;
			//On recupere les differentes activites auquelles l'utilisateur a le droit de valider dans le processus demande
			struct activity ** activite=findByPerformer(login,tableProcess->processes[process-1],&nbActivites);
			if (activite==NULL){
				message=calloc(strlen("Pas d'activite de validable pour l'utilisateur dans ce process\n")+1,sizeof(char));
				sprintf(message,"Pas d'activite de validable pour l'utilisateur dans ce process\n");
			}
			else{
				int i;
				for (i=0;i<nbActivites;i++){
					if (strcmp(activite[i]->id,idActivity)==0){
						message=validerActivite(tableProcess->processes[process-1],activity,socket);
					}
				}
				if (message==NULL){
					message=calloc(strlen("L'activite specifiee n'est pas validable par l'utilisateur\n")+1,sizeof(char));
					sprintf(message,"L'activite specifiee n'est pas validable par l'utilisateur\n");
				}
			}
		}
	}
	V(VERROUTABLEPROCESS);
	return message;
}
int ecoute_admin(char * message) {
	/*envoi a chaque operation d'un client un message aux admin en -listen */
#ifdef VERBOSE
	fprintf(stderr, "Debut Envoi message listen admin \"%s\"\n", message);
#endif
	struct message* madmin = malloc(sizeof(struct message));
	int boiteclient = connect_boite_requete(NUMREP);
	bzero(madmin->buffer, strlen(message) + 1);
	memcpy(madmin->buffer, message, strlen(message));
	madmin->code = 4;
	madmin->coupe = 0;
	madmin->numpacket = 1;
	envoyer_message(boiteclient, madmin);
	free(madmin);
	free(message);
#ifdef VERBOSE
	fprintf(stderr, "Fin Envoi message listen admin\n");
#endif
	return 0;
}
char * ls_processes(char * etat) { /* liste les etat de tous les processes */
	int i;
	int state = -1;
	char * liste = NULL;
	int size_liste = 0;
	if (etat != NULL) {
		if (strcmp(etat, "RUNNING") == 0) {
			state = RUNNING;
		}
		if (strcmp(etat, "COMPLETED") == 0) {
			state = COMPLETED;
		}
		if (state == -1) {
			return NULL;
		}
	} else {
		state = 10;
	}
	int affiche;
	P(VERROUTABLEPROCESS);
	for (i = 0; i < tableProcess->nbProcesses; i++) {
#ifdef VERBOSE
		fprintf(stderr, "Process en cours\n");
#endif
		affiche = 0;
		if (state != 10) {
			if (tableProcess->processes[i]->state == state) {
				affiche = 1;
			}
		} else {
			affiche = 1;
		}
		if (affiche) {
			char * msg;
			int size_msg = 0;
			char * etatProcess = NULL;
			if (tableProcess->processes[i]->state == RUNNING) {
				etatProcess = "RUNNING";
			} else {
				etatProcess = "COMPLETED";
			}
			size_msg = strlen(" \n");
			size_msg += strlen("Identifiant:");
			size_msg += strlen(etatProcess);
			size_msg += strlen("Etat:");
			size_msg += nbChiffres(i + 1);
			size_msg = size_msg * sizeof(char);
			msg = malloc(size_msg + 1);
			bzero(msg, size_msg);
			snprintf(msg, size_msg + 1, "Identifiant:%d Etat:%s\n", i + 1,
					etatProcess);
#ifdef VERBOSE
			fprintf(stderr, "Message:%s taille:%d\n", msg, size_msg);
#endif
			liste = realloc(liste, size_liste + size_msg);
			memcpy(liste + size_liste, msg, size_msg);
			size_liste += size_msg;
		}
	}
	if (tableProcess->nbProcesses == 0) {
		liste = malloc(strlen("Aucun process\n") * sizeof(char));
		memcpy(liste, "Aucun process\n", strlen("Aucun process\n")
				* sizeof(char));
		size_liste = strlen("Aucun process\n");
	} else {
		if (size_liste == 0) {
			liste = malloc(strlen("Aucun processus repond a vos criteres\n")
					* sizeof(char));
			memcpy(liste, "Aucun processus repond a vos criteres\n", strlen(
					"Aucun processus repond a vos criteres\n") * sizeof(char));
			size_liste = strlen("Aucun processus repond a vos criteres\n");
		}
	}
	V(VERROUTABLEPROCESS);
	liste = realloc(liste, size_liste + 1);
	liste[size_liste] = '\0';
	return liste;
}
char* recup_connect() { /* recupere liste users connecte */
	int i;
	int size = 0;
	char* list = NULL;
	char *login = NULL;
	char *nom = NULL;
	char *prenom = NULL;
	P(VERROUTABLEUSERS);
	for (i = 0; i < UserConnect->nbUser; i++) {
		login = UserConnect->users[i].login;
		nom = UserConnect->users[i].nom;
		prenom = UserConnect->users[i].prenom;
		list = (char*) realloc(list, (size + strlen(login) + strlen(nom)
				+ strlen(prenom) + 5) * sizeof(char));
		memcpy(list + size, login, strlen(login));
		memcpy(list + size + strlen(login), " : ", 3 * sizeof(char));
		memcpy(list + size + strlen(login) + 3, nom, strlen(nom));
		memcpy(list + size + strlen(login) + 3 + strlen(nom), " ", sizeof(char));
		memcpy(list + size + strlen(login) + 3 + strlen(nom) + 1, prenom,
				strlen(prenom));
		memcpy(list + size + strlen(login) + 3 + strlen(nom) + 1 + strlen(
				prenom), "\n", sizeof(char));
		size = size + strlen(login) + strlen(nom) + strlen(prenom) + 5;
	}
	list = realloc(list, size + 1);
	list[size] = '\0';
	V(VERROUTABLEUSERS);
	return list;
}

int addProcess(char * file) {  /* ajoute un process dans la table */
	struct process * processus = parse(file);
	if (processus == NULL) {
		return -1;
	}
	processus->state = RUNNING;
	P(VERROUTABLEPROCESS);
	tableProcess->processes = realloc(tableProcess->processes,
			(tableProcess->nbProcesses + 1) * sizeof(struct process*));
	tableProcess->processes[tableProcess->nbProcesses] = processus;
	tableProcess->nbProcesses++;
	V(VERROUTABLEPROCESS);
	return 0;
}

void supprimeClient(int socket) { /* supprime le client de la table */
	int i = 0;
	P(VERROUTABLEUSERS);
	while (UserConnect->users[i].socket != socket) {
		i++;
	}
	UserConnect->users[i] = UserConnect->users[UserConnect->nbUser - 1];
	UserConnect->users = (struct personne*) realloc(UserConnect->users,
			(UserConnect->nbUser - 1) * sizeof(struct personne));
	UserConnect->nbUser--;
	close(socket);
	V(VERROUTABLEUSERS);
	supprimeClientLeger(NULL);
}

void ajoutClient(int socket, char * login, char * nom, char * prenom) {
	//Ajout dans la table d'un client
	P(VERROUTABLEUSERS);
	UserConnect->users = (struct personne*) realloc(UserConnect->users,
			(UserConnect->nbUser + 1) * sizeof(struct personne));
	UserConnect->users[UserConnect->nbUser].socket = socket;
	UserConnect->users[UserConnect->nbUser].login = malloc(strlen(login) + 1);
	bzero(UserConnect->users[UserConnect->nbUser].login, strlen(login) + 1);
	memcpy(UserConnect->users[UserConnect->nbUser].login, login, strlen(login));

	UserConnect->users[UserConnect->nbUser].nom = malloc(strlen(login) + 1);
	bzero(UserConnect->users[UserConnect->nbUser].nom, strlen(nom) + 1);
	memcpy(UserConnect->users[UserConnect->nbUser].nom, nom, strlen(nom));

	UserConnect->users[UserConnect->nbUser].prenom = malloc(strlen(prenom) + 1);
	bzero(UserConnect->users[UserConnect->nbUser].prenom, strlen(prenom) + 1);
	memcpy(UserConnect->users[UserConnect->nbUser].prenom, prenom, strlen(
			prenom));
	UserConnect->nbUser = UserConnect->nbUser + 1;
	V(VERROUTABLEUSERS);
}

char * lit_commande(int socket) { /* recupere une ligne de commande (chaine de caracteres)*/
	char * donnees = NULL;
	int size = 0;
	char tmp;
	int code;
	if ((code = read(socket, &tmp, sizeof(char))) == -1) {
		perror("read");
		exit(-1);
	}
	if (code <= 0) {
		return NULL;
	}
	while (tmp != '\n') {
		size++;
		donnees = realloc(donnees, size * sizeof(char));
		donnees[size - 1] = tmp;
		if (read(socket, &tmp, sizeof(char)) == -1) {
			perror("read");
			exit(-1);
		}
	}
	donnees = realloc(donnees, (size + 1) * sizeof(char));
	donnees[size] = '\0';
	return donnees;

}

int envoie_message(int socket, char * message) {	/*envoi message au client via socket */
#ifdef VERBOSE
	fprintf(stderr, "Envoie du message \"%s\" au client\n", message);
	fprintf(stderr, "Taille du message:%d\n", strlen(message));
#endif
	return write(socket, message, strlen(message));
}

int findUser(char ** login, char ** password, char ** nom, char ** prenom,
		int fd) {		/* renvoi info de chaque utilisateur dans users */
	char * ligne = lit_commande(fd);
	if (ligne == NULL) {
		return -1;
	}
	int i = 0;
	int j = 0;
	char * result;
	result = strtok(ligne, ":");
	while (result != NULL) {
		if (i == 0) {
			*login = calloc(strlen(result) + 1, sizeof(char));
			memcpy(*login, result, strlen(result));
		}
		if (i == 1) {
			*password = calloc(strlen(result) + 1, sizeof(char));
			memcpy(*password, result, strlen(result));
		}
		if (i == 2) {
			char * result2 = strtok(result, " ");
			j = 0;
			while (result2 != NULL) {
				if (j == 0) {
					*nom = calloc(strlen(result2) + 1, sizeof(char));
					memcpy(*nom, result2, strlen(result2));
				}
				if (j == 1) {
					*prenom = calloc(strlen(result2) + 1, sizeof(char));
					memcpy(*prenom, result2, strlen(result2));
				}
				j++;
				result2 = strtok(NULL, " ");
			}
		}
		i++;
		result = strtok(NULL, ":");
	}
	free(ligne);
	return 0;
}
int uniqueConnexion(int socket, char* login) {  /* test unicite connexion client */
	char* loginuser;							/* deja connecte 1 sinon 0 */
	int i = 0;
	int trouve = 0;
#ifdef VERBOSE
		fprintf(stderr, "login a tester %s\n",login);
#endif
	while (i < UserConnect->nbUser && trouve!=1) {
		loginuser = calloc(strlen(UserConnect->users[i].login) + 1, sizeof(char));
		strcpy(loginuser,UserConnect->users[i].login);
#ifdef VERBOSE
		fprintf(stderr, "loginuser table %s\n",loginuser);
#endif
		if (strcmp(login, loginuser) == 0) {
			trouve = 1;
		}
		i++;
		free(loginuser);
	}
	return trouve;
}


int handleLogin(int socket, char ** loginUser) {	/* tests pour connexion client */
	int trouve = 0;
	envoie_message(socket, "Login :");
	char * loginuser = lit_commande(socket);
	if (loginuser == NULL) {
		return -1;
	}
	envoie_message(socket, "Password :");
	char * passworduser = lit_commande(socket);
	if (passworduser == NULL) {
		return -1;
	}
#ifdef VERBOSE
	fprintf(stderr, "je recoit %s,%s\n", loginuser, passworduser);
#endif
	int fd = open(fichierUsers, O_RDONLY);
	if (fd < 0) {
#ifdef VERBOSE
		fprintf(stderr, "fichier:%s\n", fichierUsers);
#endif
		perror("open");
		exit(-1);
	}
	char *login;
	char *password;
	char *nom;
	char *prenom;
	while (findUser(&login, &password, &nom, &prenom, fd) == 0 && trouve == 0) {
#ifdef VERBOSE
		fprintf(stderr, "login : %s\n", login);
		fprintf(stderr, "password : %s\n", password);
		fprintf(stderr, "nom : %s\n", nom);
		fprintf(stderr, "prenom : %s\n", prenom);
#endif
		if (strcmp(login, loginuser) == 0 && strcmp(password, passworduser)
				== 0) {
			if (uniqueConnexion(socket, login) == 0) {
#ifdef VERBOSE
		fprintf(stderr, "trouve pas connecte\n");
#endif
				trouve = 1;
				ajoutClient(socket, login, nom, prenom);
			}
			else{
#ifdef VERBOSE
		fprintf(stderr, "trouve deja connecte\n");
#endif
				trouve = 2;
			}
			*loginUser = login;
		} else {
			free(login);
		}
		free(password);
		free(nom);
		free(prenom);
	}
	if (trouve == 1) {
#ifdef VERBOSE
		fprintf(stderr, "Trouve\n");
#endif
		envoie_message(socket, "Connection reussie\n");
	} else if (trouve == 2) {
#ifdef VERBOSE
		fprintf(stderr, "User deja connecte\n");
#endif
		envoie_message(socket, "Deja connecte\n");
		return -1;
	}else{
#ifdef VERBOSE
		fprintf(stderr, "pas trouve\n");
#endif
		envoie_message(socket, "404 not found\n");
		return -1;
	}
	close(fd);
	return 0;
}

////Verification du format idProcess.idActivity
int verifBonFormat(char * donnees, int *process, char ** activite) {
	int idx1 = 0;
	while (isdigit(donnees[idx1])) {
		idx1++;
	}
	if (donnees[idx1] != '.') {
		return -1;

	} else {
		donnees[idx1] = '\0';
		idx1++;
		int idx2 = idx1;
		while (isalnum(donnees[idx2])) {
			idx2++;
		}
		if (donnees[idx2] != '\0') {
			return -1;
		} else {
			*process = atoi(donnees);
			*activite = calloc(strlen(donnees + idx1) + 1, sizeof(char));
			memcpy(*activite, donnees + idx1, strlen(donnees + idx1));
#ifdef VERBOSE
			donnees[idx1 - 1] = '.';
			fprintf(stderr, "Donnees:%s\n", donnees);
			fprintf(stderr, "Process number %d\n", *process);
			fprintf(stderr, "Activity number %s\n", *activite);
#endif

			return 0;
		}
	}
}
int ModeToDo(int socket, char * loginUser) {
	envoie_message(socket, "Mode TODO,Veuillez entrer votre commande:");
	char * donnees = lit_commande(socket);
	if (donnees == NULL) {
		supprimeClient(socket);
		return -1;
	}
	while (strcmp(donnees, "exit") != 0) {
		if (strncmp(donnees, "ls", 2) == 0) {
			if (strlen(donnees) == strlen("ls") + 1) {
				envoie_message(socket, "Usage: ls <idProcess.idActivity>\n");
			} else {
				int process = 0;
				char * activite = 0;
				if (strlen(donnees) != strlen("ls")) {
					//On vérifie que l'on passe bien en parametre idProcess.idActivity
					if (verifBonFormat(donnees + 3, &process, &activite) < 0) {
						envoie_message(socket,
								"Usage: ls <idProcess.idActivity>\n");
					} else {
						char * activitesAccessibles = activites_accessibles(
								process, activite, loginUser);
						envoie_message(socket, activitesAccessibles);
					}
				} else {
					char * activitesAccessibles = activites_accessibles(
							process, activite, loginUser);
					envoie_message(socket, activitesAccessibles);
				}
			}
		}
		if (strncmp(donnees, "valider", 7) == 0) {
			if (strlen(donnees) == strlen("valider") + 1) {
				envoie_message(socket,
						"Usage: valider <idProcess.idActivity>\n");
			} else {
				int process = 0;
				char * activite = 0;
				if (strlen(donnees) != strlen("valider")) {
					//On vérifie que l'on passe bien en parametre idProcess.idActivity
					if (verifBonFormat(donnees + strlen("valider") + 1,
							&process, &activite) < 0) {
						envoie_message(socket,
								"Usage: valider <idProcess.idActivity>\n");
					} else {
						char * message = valider(process, activite, loginUser,
								socket);
						envoie_message(socket, message);
					}
				} else {
					char * message = valider(process, activite, loginUser,
							socket);
					envoie_message(socket, message);
				}
			}
		}
		free(donnees);
		envoie_message(socket, "Mode TODO,Veuillez entrer votre commande:");
		donnees = lit_commande(socket);
		if (donnees == NULL) {
			supprimeClient(socket);
			return -1;
		}
	}
	return 0;
}
void* gestionClient(void* arg) {
	int socket = (*((int*) arg));
	char * nom = SocketVersNom(socket);
	char * message;
	char * loginUser;
	if (handleLogin(socket, &loginUser) < 0) {
		close(socket);
		return NULL;
	}
#ifdef VERBOSE
	fprintf(stderr, "Connexion du client :%s %d\n", loginUser,
			strlen(loginUser));
#endif
	message = calloc(strlen("connexion client ") + strlen(loginUser) + 2,
			sizeof(char));
	sprintf(message, "connexion client %s\n", loginUser);
	ecoute_admin(message);
	char * donnees = NULL;
	while (1) {	/* traitement commande client */
		envoie_message(socket, "Veuillez entrer votre commande:");
		donnees = lit_commande(socket);
		if (donnees == NULL) {
			supprimeClient(socket);
			return NULL;
		}
		if (strcmp(donnees, "exit") == 0) {
			message = calloc(strlen("deconnexion client ") + strlen(loginUser)
					+ 1, sizeof(char));
			sprintf(message, "deconnexion client %s\n", loginUser);
			ecoute_admin(message);
			free(donnees);
			break;
		}
		if (strcmp(donnees, "aide") == 0) {
			message = calloc(strlen("aide client ") + strlen(loginUser) + 1,
					sizeof(char));
			sprintf(message, "aide client %s\n", loginUser);
			ecoute_admin(message);
			envoie_message(socket, "Liste des commandes disponibles :\n");
			envoie_message(socket,
					"aide : permet de connaitre les commandes disponibles\n");
			envoie_message(
					socket,
					"ToDo : permet de passer en mode gestion de la To-Do List, i.e., gerer les activites assignees a l'utilisateur\n");
			envoie_message(socket,
					"connected_users : permet de connaitre tous les utilisateurs connectes\n");
			envoie_message(
					socket,
					"ls_processes : permet de lister l'identifiant et l'etat de tous les processus. Cette commande peut eventuellement prendre en parametre un etat de processus afin de ne lister que les processus dans cet etat\n");
			envoie_message(
					socket,
					"ls_process <id-process> : permet de recuperer toutes les informations associees a un processus particulier\n");
			envoie_message(socket,
					"create_process <file> : permet de creer une nouvelle instance de processus\n");
			envoie_message(socket,
					"exit : permet de quitter l'application et se deconnecter\n");
		}
		if (strcmp(donnees, "ToDo") == 0) {
			message = calloc(strlen("ToDo client ") + strlen(loginUser) + 1,
					sizeof(char));
			sprintf(message, "ToDo client %s\n", loginUser);
			ecoute_admin(message);
			if (ModeToDo(socket, loginUser) < 0) {
				return NULL;
			}
		}
		if (strcmp(donnees, "connected_users") == 0) {
			message = calloc(strlen("liste utilisateur connecte client ")
					+ strlen(loginUser) + 1, sizeof(char));
			sprintf(message, "liste utilisateur connecte client %s\n",
					loginUser);
			ecoute_admin(message);
			char * list = recup_connect();
			envoie_message(socket, list);
			free(list);
		}
		if (strncmp(donnees, "create_process", strlen("create_process")) == 0) {
			message = calloc(strlen("creation processes client ") + strlen(
					loginUser) + 1, sizeof(char));
			sprintf(message, "creation processes client %s\n", loginUser);
			ecoute_admin(message);
			//test si un argument est en parametre
			if (strlen(donnees) - strlen("create_process") < 2) {
				envoie_message(socket, "Usage: create_process file\n");
			} else {
				//on recupere le fichier a ajouter
				char * file =
						malloc(strlen(donnees) - strlen("create_process"));
				bzero(file, strlen(donnees) - strlen("create_process"));
				memcpy(file, donnees + strlen("create_process") + 1, strlen(
						donnees) - strlen("create_process") - 1);
				if (addProcess(file) == -1) {
					envoie_message(socket, "processus inexistant\n");
				} else {
					envoie_message(socket, "processus ajoute\n");
				}
				free(file);
			}

		}

		if (strncmp(donnees, "ls_processes", strlen("ls_processes")) == 0) {
			message = calloc(strlen("ls processes client ") + strlen(loginUser)
					+ 1, sizeof(char));
			sprintf(message, "ls processes client %s\n", loginUser);
			ecoute_admin(message);
			char * m;
			//On Teste si on doit utiliser la version sans parametre ou avec
			if (strlen(donnees) == strlen("ls_processes")) {
				m = ls_processes(NULL);
				envoie_message(socket, m);
				free(m);
			} else {
				if (strlen(donnees) - strlen("ls_processes") == 1) {
					envoie_message(socket, "Usage: ls_processes <idProcess>\n");
				} else {
					char * etat = malloc(strlen(donnees) - strlen(
							"ls_processes"));
					bzero(etat, strlen(donnees) - strlen("ls_processes"));
					memcpy(etat, donnees + strlen("ls_processes") + 1, strlen(
							donnees) - strlen("ls_processes") - 1);
					m = ls_processes(etat);
					free(etat);
					envoie_message(socket, m);
					free(m);
				}
			}
		} else {
			if (strncmp(donnees, "ls_process", strlen("ls_process")) == 0) {
				message = calloc(strlen("ls process client ") + strlen(
						loginUser) + 1, sizeof(char));
				sprintf(message, "ls process client %s\n", loginUser);
				ecoute_admin(message);
				char * m;
				//Argument obligatoire a tester
				if (strlen(donnees) - strlen("ls_process") < 2) {
					envoie_message(socket, "Usage: ls_process idProcess\n");
				} else {
					int idx = strlen("ls_process") + 2;
					while (isdigit(donnees[idx])) {
						idx++;
					}
					if (idx != strlen(donnees)) {
						envoie_message(socket, "Usage: ls_process idProcess\n");
					} else {
						int idProcess =
								atoi(donnees + strlen("ls_process") + 1);
						m = ls_process(idProcess);
						envoie_message(socket, m);
					}
				}
			}
		}
		free(donnees);
	}
	free(nom);
	free(loginUser);
	supprimeClient(socket);
	return NULL;
}
